Real URLs: Cloudflare Pages + BrowserRouter, dead-page cut, a11y ride-alongs#62
Merged
Conversation
Every deep link previously served HTTP 404 and bounced to a hash route; a publication arguing provenance had uncitable addresses. - router.tsx: createHashRouter → createBrowserRouter. Legacy /#/… citations resolve at module scope (before the router captures location) via new utils/legacyHashRedirect.ts — 6 tests; auth hashes are ignored and left to the OAuth interceptor. - main.tsx: post-auth URL cleanup writes plain paths, PostHog capture_pageview → 'history_change' so pushState pageviews count. - 20 hash hrefs across the routed surface rewritten to real paths; MagazineFrame's goHome now uses useNavigate. - public/_redirects: /* /index.html 200 (real files served first, so artifacts and plates stay static 200s). - scripts/build-sitemap.mjs replaces the stale 4-URL sitemap (it listed /#/engine) with 9 routes + 68 issues, regenerated in CI. - deploy.yml now presses to Cloudflare Pages (wrangler-action v3, project kernel-chat); all law gates kept. deploy-gh-pages.yml is the workflow_dispatch rollback; 404.html + CNAME retained for it. - e2e specs updated to path URLs. PUBLISHING.md §VII rewritten. Gates: tsc clean, 794/794 tests, build 236.27KB gzip JS (<300KB). Verified in vite preview: /issues/421 direct 200, /#/issues/415 resolves to the 415 spread, artifacts/index.html serves static. Co-Authored-By: Claude Fable 5 <[email protected]>
Count what gets read; cut what doesn't. None of these nine pages is reachable from router.tsx and none is imported outside its own file (grep-audited; the sole 'AdminPage' hit was the substring inside WorkspaceAdminPage, itself cut): LeaderboardPage, PlayPage, TerminalPage, PricingPage (billing died 2026-04-16; a price page contradicts the ¥0 masthead), AdminPage, WorkspaceAdminPage, ApiDocsPage, AuthorProfilePage, ExplorePage. Exclusive dependencies go with them: useSynthesisState, discovery/SearchBar, TopicGrid. Kept deliberately: the EnginePage chat tree (parked product, not junk) and FeedCard/AuthorCard/useDiscovery/discoveryStore, which the parked tree still imports. public/play and synthesis-state stay — the build:synth pipeline owns them. Gates: tsc clean, 794/794 tests, build 236.27KB gzip JS. Co-Authored-By: Claude Fable 5 <[email protected]>
The colophon's back-to-top control measured 98×13 — half the WCAG 2.5.8 minimum. Padding + negative margin grow the hit area to 122×44 while the printed mark stays optically where it was (white-space: nowrap keeps it on one line inside the 40px-wide colophon column; the earlier declaration order let the block's own padding: 0 win, now removed). Layout gains the keyboard reader's shortcut: a skip link ahead of the masthead, off-canvas until focused, folio grammar, targeting main#feature-well (tabIndex -1). Styled with house tokens only. Gates: adherence + editorial clean, tsc clean, 794/794 tests. Verified in vite preview: target measures 122×44; link focusable with the :focus reveal rule in the sheet. Co-Authored-By: Claude Fable 5 <[email protected]>
Co-Authored-By: Claude Fable 5 <[email protected]>
deploy.yml and package.json both reference 'npm run sitemap' → scripts/build-sitemap.mjs, but the file itself sat untracked on disk and was never git-added in the routing commit. CI on this PR would have failed at the sitemap step. Caught during THE STACKS Task 4 review while checking out a sibling branch and finding the script missing. Co-Authored-By: Claude Fable 5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Every deep link becomes a real, citable URL.
kernel.chat/issues/421currently serves an HTTP 404 and bounces to/#/issues/421— uncitable addresses on a publication whose thesis is provenance.createHashRouter→createBrowserRouter; legacy/#/…citations resolve at module scope viasrc/utils/legacyHashRedirect.ts(6 tests; auth hashes left to the OAuth interceptor)public/_redirectsSPA fallback; artifacts/plates/sitemap stay static 200s/#/engine)deploy-gh-pages.ymlis the dispatch-only rollbackBefore merging (owner setup, ~10 min)
kernel-chat(direct upload, no git integration — CI uploadsdist/)CLOUDFLARE_API_TOKEN(Pages:Edit) andCLOUDFLARE_ACCOUNT_IDkernel-chat.pages.dev: add thekernel.chatcustom domain, repoint DNS, remove the domain from GH Pages settingsRollback:
gh workflow run deploy-gh-pages.yml+ DNS back to GH Pages.Verification
tsc clean · 794/794 tests · 236.33KB gzip JS (<300KB) · vite preview:
/issues/421direct,/#/issues/415resolves to the 415 spread,artifacts/index.htmlstatic, zero console errors.🤖 Generated with Claude Code